﻿using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Xml.Linq;
using YawetagLib.Utilities;

namespace YawetagLib.Data.Xml
{
    public static class Extensions
    {
        public static void SetAttibuteAt(this XElement element, string attributeName, object value)
        {
            XAttribute attribute = element.Attribute(attributeName);

            if (attribute != null) { attribute.SetValue(value); }
        }

        public static string GetAttibuteAt(this XElement element, string attributeName)
        {
            XAttribute attribute = element.Attribute(attributeName);

            return attribute != null ? attribute.Value : string.Empty;
        }

        public static object GetAttibuteAt(this XElement element, string attributeName, Type propertyType)
        {
            return element.GetAttibuteAt(attributeName).ConvertTo(propertyType);
        }

        public static T GetAttibuteAt<T>(this XElement element, string attributeName)
        {
            return element.GetAttibuteAt(attributeName).ConvertTo<T>();
        }

        public static Func<XElement, bool> ToXPredicate<TEntity>(this Expression<Func<TEntity, bool>> expression)
        {
            return ((Expression<Func<XElement, bool>>)new EntityToXElementModifier().Modify(expression)).Compile();
        }

        public static XEntityAttribute GetXEntityAttribute(this Type type)
        {
            return type.GetSingleAttribute<XEntityAttribute>();
        }

        public static bool IsXFieldProperty(this PropertyInfo propertyInfo)
        {
            return propertyInfo.HasAttribute<XFieldAttribute>();
        }

        public static XReferenceAttribute GetXReferenceAttribute(this PropertyInfo propertyInfo)
        {
            return propertyInfo.GetSingleAttribute<XReferenceAttribute>();
        }

        public static bool IsXReferenceProperty(this PropertyInfo propertyInfo)
        {
            return propertyInfo.HasAttribute<XReferenceAttribute>();
        }

        public static string GetEntityReferenceKey(this Type entityType, int entityID)
        {
            return string.Format("{0}-{1}", entityType.Name, entityID);
        }

        public static int GetElementKey(this XElement element, string keyName)
        {
            return element.GetAttibuteAt<int>(keyName);
        }

        public static int GetElementID<TEntity>(this XElement element)
        {
            return element.GetElementKey(typeof(TEntity).GetXEntityAttribute().PrimaryKeyName);
        }

        public static int GetEntityID<TEntity>(this TEntity entity)
        {
            return entity.GetAt<int>(typeof(TEntity).GetXEntityAttribute().PrimaryKeyName);
        }

        public static void SetEntityID<TEntity>(this TEntity entity, int entityID)
        {
            typeof(TEntity).GetProperty(typeof(TEntity).GetXEntityAttribute().PrimaryKeyName).SetValue(entity, entityID, null);
        }
    }
}
